home *** CD-ROM | disk | FTP | other *** search
/ Apple WWDC 1996 / WWDC96_1996 (CD).toast / Technology Materials / MacApp Release 10 / MacApp Release 10 - HD Ready / Libraries / Framework / Sources / UBusyCursor.cp < prev    next >
Encoding:
Text File  |  1996-04-03  |  32.2 KB  |  1,084 lines  |  [TEXT/MPS ]

  1. //----------------------------------------------------------------------------------------
  2. // UBusyCursor.cp 
  3. // Copyright © 1985-96 by Apple Computer, Inc. All rights reserved.
  4. //----------------------------------------------------------------------------------------
  5.  
  6. #ifndef __UBUSYCURSOR__
  7. #include "UBusyCursor.h"
  8. #endif
  9.  
  10. // MacApp
  11.  
  12. #ifndef __UCOREUTILITIES__
  13. #include "UCoreUtilities.h"
  14. #endif
  15.  
  16. #ifndef __UFAILURE__
  17. #include "UFailure.h"
  18. #endif
  19.  
  20. #ifndef __UMEMORY__
  21. #include "UMemory.h"
  22. #endif
  23.  
  24. #ifndef __UPATCH__
  25. #include "UPatch.h"
  26. #endif
  27.  
  28. // Toolbox
  29.  
  30. #ifndef __LOWMEM__
  31. #include <LowMem.h>
  32. #endif
  33.  
  34. #ifndef __RESOURCES__
  35. #include <Resources.h>
  36. #endif
  37.  
  38. #ifndef __TOOLUTILS__
  39. #include <ToolUtils.h>
  40. #endif
  41.  
  42. #ifndef __TRAPS__
  43. #include <Traps.h>
  44. #endif
  45.  
  46. //----------------------------------------------------------------------------------------
  47.  
  48. #ifndef qPatchEventAvail
  49. #define qPatchEventAvail    0
  50. #endif
  51.  
  52. //----------------------------------------------------------------------------------------
  53. const ResNumber kAcurRsrcID = 256;
  54.  
  55. //----------------------------------------------------------------------------------------
  56. // static data members
  57. //----------------------------------------------------------------------------------------
  58. TBusyCursor* TBusyCursor::fgBusyCursor;
  59. Boolean TBusyCursor::pBusyCursorVBLInstalled;        // used for proper failure handling
  60.  
  61. TBusyCursorPtr& gBusyCursor = TBusyCursor::fgBusyCursor;
  62.  
  63. #if qPatchEventAvail
  64. //========================================================================================
  65. // CLASS PatchEventAvail
  66. //========================================================================================
  67. #pragma segment MABusyCursorRes
  68.  
  69. typedef pascal Boolean (*EventAvailType)(short eventMask, EventRecord* theEvent);
  70.  
  71. #if GENERATINGCFM
  72. typedef UniversalProcPtr EventAvailUPP;
  73. #else
  74. typedef ProcPtr EventAvailUPP;
  75. #endif
  76.     
  77. enum
  78. {
  79.     uppEventAvailProcInfo = kPascalStackBased
  80.          | RESULT_SIZE(SIZE_CODE(sizeof(Boolean)))
  81.          | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(short)))
  82.          | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(EventRecord*)))
  83. };
  84.  
  85. #if GENERATINGCFM
  86. #define NewEventAvailProc(userRoutine)  \
  87.         (EventAvailUPP) NewRoutineDescriptor((ProcPtr)(userRoutine), uppEventAvailProcInfo, GetCurrentISA())
  88. #else
  89. #define NewEventAvailProc(userRoutine)        \
  90.         ((EventAvailUPP) (userRoutine))
  91. #endif
  92.     
  93. #if GENERATINGCFM
  94. #define CallEventAvailProc(userRoutine, eventMask, theEvent)        \
  95.         CallUniversalProc((UniversalProcPtr)(userRoutine), uppEventAvailProcInfo, (eventMask), (theEvent))
  96. #else
  97. #define CallEventAvailProc(userRoutine, eventMask, theEvent)        \
  98.         (*(userRoutine))((eventMask), (theEvent))
  99. #endif
  100.     
  101. //========================================================================================
  102.  
  103. class PatchEventAvail : public TrapPatch
  104. {
  105.   public:
  106.     void Install(EventAvailType routine);
  107.     Boolean CallInherited(short eventMask, EventRecord* theEvent);
  108. };
  109.  
  110. //--------------------------------------------------------------------------------------------------
  111. #pragma segment MABusyCursorRes
  112.  
  113. void PatchEventAvail::Install(EventAvailType routine)
  114. {
  115.     patchRoutine = NewEventAvailProc(StripLong(routine));
  116.     FailNIL(patchRoutine);
  117.     PatchTrap(_EventAvail, patchRoutine);
  118. }
  119.  
  120. //--------------------------------------------------------------------------------------------------
  121. #pragma segment MABusyCursorRes
  122.  
  123. Boolean PatchEventAvail::CallInherited(short eventMask, EventRecord* theEvent)
  124. {
  125.     return CallEventAvailProc((EventAvailType) oldTrapAddr, eventMask, theEvent);
  126. }
  127. #endif // qPatchEventAvail
  128.  
  129. //========================================================================================
  130. // CLASS PatchGetNextEvent
  131. //========================================================================================
  132. #pragma segment MABusyCursorRes
  133.  
  134. typedef pascal Boolean (*GetNextEventType)(short eventMask, EventRecord* theEvent);
  135.  
  136. #if GENERATINGCFM
  137. typedef UniversalProcPtr GetNextEventUPP;
  138. #else
  139. typedef ProcPtr GetNextEventUPP;
  140. #endif
  141.     
  142. enum
  143. {
  144.     uppGetNextEventProcInfo = kPascalStackBased
  145.          | RESULT_SIZE(SIZE_CODE(sizeof(Boolean)))
  146.          | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(short)))
  147.          | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(EventRecord*)))
  148. };
  149.  
  150. #if GENERATINGCFM
  151. #define NewGetNextEventProc(userRoutine)  \
  152.         (GetNextEventUPP) NewRoutineDescriptor((ProcPtr)(userRoutine), uppGetNextEventProcInfo, GetCurrentISA())
  153. #else
  154. #define NewGetNextEventProc(userRoutine)        \
  155.         ((GetNextEventUPP) (userRoutine))
  156. #endif
  157.     
  158. #if GENERATINGCFM
  159. #define CallGetNextEventProc(userRoutine, eventMask, theEvent)        \
  160.         CallUniversalProc((UniversalProcPtr)(userRoutine), uppGetNextEventProcInfo, (eventMask), (theEvent))
  161. #else
  162. #define CallGetNextEventProc(userRoutine, eventMask, theEvent)        \
  163.         (*(userRoutine))((eventMask), (theEvent))
  164. #endif
  165.     
  166. class PatchGetNextEvent : public TrapPatch
  167. {
  168.   public:
  169.     void Install(GetNextEventType routine);
  170.     Boolean CallInherited(short eventMask, EventRecord* theEvent);
  171. };
  172.  
  173. //--------------------------------------------------------------------------------------------------
  174. #pragma segment MABusyCursorRes
  175.  
  176. void PatchGetNextEvent::Install(GetNextEventType routine)
  177. {
  178.     patchRoutine = NewGetNextEventProc(StripLong(routine));
  179.     FailNIL(patchRoutine);
  180.     PatchTrap(_GetNextEvent, patchRoutine);
  181. }
  182.  
  183. //--------------------------------------------------------------------------------------------------
  184. #pragma segment MABusyCursorRes
  185.  
  186. Boolean PatchGetNextEvent::CallInherited(short eventMask, EventRecord* theEvent)
  187. {
  188.     return CallGetNextEventProc((GetNextEventType) oldTrapAddr, eventMask, theEvent);
  189. }
  190.  
  191. //========================================================================================
  192. // CLASS PatchInitCursor
  193. //========================================================================================
  194. #pragma segment MABusyCursorRes
  195.  
  196. typedef pascal void (*InitCursorType)(void);
  197.  
  198. #if GENERATINGCFM
  199. typedef UniversalProcPtr InitCursorUPP;
  200. #else
  201. typedef ProcPtr InitCursorUPP;
  202. #endif
  203.     
  204. enum
  205. {
  206.     uppInitCursorProcInfo = kPascalStackBased
  207. };
  208.  
  209. #if GENERATINGCFM
  210. #define NewInitCursorProc(userRoutine)  \
  211.         (InitCursorUPP) NewRoutineDescriptor((ProcPtr)(userRoutine), uppInitCursorProcInfo, GetCurrentISA())
  212. #else
  213. #define NewInitCursorProc(userRoutine)        \
  214.         ((InitCursorUPP) (userRoutine))
  215. #endif
  216.  
  217. #if GENERATINGCFM
  218. #define CallInitCursorProc(userRoutine)        \
  219.         CallUniversalProc((UniversalProcPtr)(userRoutine), uppInitCursorProcInfo)
  220. #else
  221. #define CallInitCursorProc(userRoutine)        \
  222.         (*(userRoutine))()
  223. #endif
  224.     
  225. class PatchInitCursor : public TrapPatch
  226. {
  227.   public:
  228.     void Install(InitCursorType routine);
  229.     void CallInherited();
  230. };
  231.  
  232. //--------------------------------------------------------------------------------------------------
  233. #pragma segment MABusyCursorRes
  234.  
  235. void PatchInitCursor::Install(InitCursorType routine)
  236. {
  237.     patchRoutine = NewInitCursorProc(StripLong(routine));
  238.     FailNIL(patchRoutine);
  239.     PatchTrap(_InitCursor, patchRoutine);
  240. }
  241.  
  242. //--------------------------------------------------------------------------------------------------
  243. #pragma segment MABusyCursorRes
  244.  
  245. void PatchInitCursor::CallInherited()
  246. {
  247.     CallInitCursorProc((InitCursorType) oldTrapAddr);
  248. }
  249.  
  250. //========================================================================================
  251. // CLASS PatchSetCCursor
  252. //========================================================================================
  253. #pragma segment MABusyCursorRes
  254.  
  255. typedef pascal void (*SetCCursorType)(CCrsrHandle cCrsr);
  256.  
  257. #if GENERATINGCFM
  258. typedef UniversalProcPtr SetCCursorUPP;
  259. #else
  260. typedef ProcPtr SetCCursorUPP;
  261. #endif
  262.     
  263. enum
  264. {
  265.     uppSetCCursorProcInfo = kPascalStackBased
  266.          | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(CCrsrHandle)))
  267. };
  268.  
  269. #if GENERATINGCFM
  270. #define NewSetCCursorProc(userRoutine)  \
  271.         (SetCCursorUPP) NewRoutineDescriptor((ProcPtr)(userRoutine), uppSetCCursorProcInfo, GetCurrentISA())
  272. #else
  273. #define NewSetCCursorProc(userRoutine)        \
  274.         ((SetCCursorUPP) (userRoutine))
  275. #endif
  276.     
  277. #if GENERATINGCFM
  278. #define CallSetCCursorProc(userRoutine, cCrsr)        \
  279.         CallUniversalProc((UniversalProcPtr)(userRoutine), uppSetCCursorProcInfo, (cCrsr))
  280. #else
  281. #define CallSetCCursorProc(userRoutine, cCrsr)        \
  282.         (*(userRoutine))((cCrsr))
  283. #endif
  284.     
  285. class PatchSetCCursor : public TrapPatch
  286. {
  287.   public:
  288.     void Install(SetCCursorType routine);
  289.     void CallInherited(CCrsrHandle cCrsr);
  290. };
  291.  
  292. //--------------------------------------------------------------------------------------------------
  293. #pragma segment MABusyCursorRes
  294.  
  295. void PatchSetCCursor::Install(SetCCursorType routine)
  296. {
  297.     patchRoutine = NewSetCCursorProc(StripLong(routine));
  298.     FailNIL(patchRoutine);
  299.     PatchTrap(_SetCCursor, patchRoutine);
  300. }
  301.  
  302. //--------------------------------------------------------------------------------------------------
  303. #pragma segment MABusyCursorRes
  304.  
  305. void PatchSetCCursor::CallInherited(CCrsrHandle cCrsr)
  306. {
  307.     CallSetCCursorProc((SetCCursorType) oldTrapAddr, cCrsr);
  308. }
  309.  
  310. //========================================================================================
  311. // CLASS PatchSetCursor
  312. //========================================================================================
  313. #pragma segment MABusyCursorRes
  314.  
  315. typedef pascal void (*SetCursorType)(const Cursor *crsr);
  316.  
  317. #if GENERATINGCFM
  318. typedef UniversalProcPtr SetCursorUPP;
  319. #else
  320. typedef ProcPtr SetCursorUPP;
  321. #endif
  322.     
  323. enum
  324. {
  325.     uppSetCursorProcInfo = kPascalStackBased
  326.          | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(Cursor *)))
  327. };
  328.  
  329. #if GENERATINGCFM
  330. #define NewSetCursorProc(userRoutine)  \
  331.         (SetCursorUPP) NewRoutineDescriptor((ProcPtr)(userRoutine), uppSetCursorProcInfo, GetCurrentISA())
  332. #else
  333. #define NewSetCursorProc(userRoutine)        \
  334.         ((SetCursorUPP) (userRoutine))
  335. #endif
  336.     
  337. #if GENERATINGCFM
  338. #define CallSetCursorProc(userRoutine, crsr)        \
  339.         CallUniversalProc((UniversalProcPtr)(userRoutine), uppSetCursorProcInfo, (crsr))
  340. #else
  341. #define CallSetCursorProc(userRoutine, crsr)        \
  342.         (*(userRoutine))(crsr)
  343. #endif
  344.     
  345. class PatchSetCursor : public TrapPatch
  346. {
  347.   public:
  348.     void Install(SetCursorType routine);
  349.     void CallInherited(const Cursor *crsr);
  350. };
  351.  
  352. //--------------------------------------------------------------------------------------------------
  353. #pragma segment MABusyCursorRes
  354.  
  355. void PatchSetCursor::Install(SetCursorType routine)
  356. {
  357.     patchRoutine = NewSetCursorProc(StripLong(routine));
  358.     FailNIL(patchRoutine);
  359.     PatchTrap(_SetCursor, patchRoutine);
  360. }
  361.  
  362. //--------------------------------------------------------------------------------------------------
  363. #pragma segment MABusyCursorRes
  364.  
  365. void PatchSetCursor::CallInherited(const Cursor *crsr)
  366. {
  367.     CallSetCursorProc((SetCursorType) oldTrapAddr, crsr);
  368. }
  369.  
  370. //========================================================================================
  371. // CLASS PatchStillDown
  372. //========================================================================================
  373. #pragma segment MABusyCursorRes
  374.  
  375. typedef pascal Boolean (*StillDownType)();
  376.  
  377. #if GENERATINGCFM
  378. typedef UniversalProcPtr StillDownUPP;
  379. #else
  380. typedef ProcPtr StillDownUPP;
  381. #endif
  382.     
  383. enum
  384. {
  385.     uppStillDownProcInfo = kPascalStackBased
  386.          | RESULT_SIZE(SIZE_CODE(sizeof(Boolean)))
  387. };
  388.  
  389. #if GENERATINGCFM
  390. #define NewStillDownProc(userRoutine)  \
  391.         (StillDownUPP) NewRoutineDescriptor((ProcPtr)(userRoutine), uppStillDownProcInfo, GetCurrentISA())
  392. #else
  393. #define NewStillDownProc(userRoutine)        \
  394.         ((StillDownUPP) (userRoutine))
  395. #endif
  396.     
  397. #if GENERATINGCFM
  398. #define CallStillDownProc(userRoutine)        \
  399.         CallUniversalProc((UniversalProcPtr)(userRoutine), uppStillDownProcInfo)
  400. #else
  401. #define CallStillDownProc(userRoutine)        \
  402.         (*(userRoutine))()
  403. #endif
  404.     
  405. class PatchStillDown : public TrapPatch
  406. {
  407.   public:
  408.     void Install(StillDownType routine);
  409.     Boolean CallInherited();
  410. };
  411.  
  412. //--------------------------------------------------------------------------------------------------
  413. #pragma segment MABusyCursorRes
  414.  
  415. void PatchStillDown::Install(StillDownType routine)
  416. {
  417.     patchRoutine = NewStillDownProc(StripLong(routine));
  418.     FailNIL(patchRoutine);
  419.     PatchTrap(_StillDown, patchRoutine);
  420. }
  421.  
  422. //--------------------------------------------------------------------------------------------------
  423. #pragma segment MABusyCursorRes
  424.  
  425. Boolean PatchStillDown::CallInherited()
  426. {
  427.     return CallStillDownProc((StillDownType) oldTrapAddr);
  428. }
  429.  
  430. //========================================================================================
  431. // CLASS PatchWaitMouseUp
  432. //========================================================================================
  433. #pragma segment MABusyCursorRes
  434.  
  435. typedef pascal Boolean (*WaitMouseUpType)();
  436.  
  437. #if GENERATINGCFM
  438. typedef UniversalProcPtr WaitMouseUpUPP;
  439. #else
  440. typedef ProcPtr WaitMouseUpUPP;
  441. #endif
  442.     
  443. enum
  444. {
  445.     uppWaitMouseUpProcInfo = kPascalStackBased
  446.          | RESULT_SIZE(SIZE_CODE(sizeof(Boolean)))
  447. };
  448.  
  449. #if GENERATINGCFM
  450. #define NewWaitMouseUpProc(userRoutine)  \
  451.         (WaitMouseUpUPP) NewRoutineDescriptor((ProcPtr)(userRoutine), uppWaitMouseUpProcInfo, GetCurrentISA())
  452. #else
  453. #define NewWaitMouseUpProc(userRoutine)        \
  454.         ((WaitMouseUpUPP) (userRoutine))
  455. #endif
  456.     
  457. #if GENERATINGCFM
  458. #define CallWaitMouseUpProc(userRoutine)        \
  459.         CallUniversalProc((UniversalProcPtr)(userRoutine), uppWaitMouseUpProcInfo)
  460. #else
  461. #define CallWaitMouseUpProc(userRoutine)        \
  462.         (*(userRoutine))()
  463. #endif
  464.     
  465. class PatchWaitMouseUp : public TrapPatch
  466. {
  467.   public:
  468.     void Install(WaitMouseUpType routine);
  469.     Boolean CallInherited();
  470. };
  471.  
  472. //--------------------------------------------------------------------------------------------------
  473. #pragma segment MABusyCursorRes
  474.  
  475. void PatchWaitMouseUp::Install(WaitMouseUpType routine)
  476. {
  477.     patchRoutine = NewWaitMouseUpProc(StripLong(routine));
  478.     FailNIL(patchRoutine);
  479.     PatchTrap(_WaitMouseUp, patchRoutine);
  480. }
  481.  
  482. //--------------------------------------------------------------------------------------------------
  483. #pragma segment MABusyCursorRes
  484.  
  485. Boolean PatchWaitMouseUp::CallInherited()
  486. {
  487.     return CallWaitMouseUpProc((WaitMouseUpType) oldTrapAddr);
  488. }
  489.  
  490. //========================================================================================
  491.  
  492. #if qPatchEventAvail
  493. static PatchEventAvail        pEAPatch;                    // patch for EventAvail 
  494. #endif
  495. static PatchGetNextEvent    pGNEPatch;                    // patch for GetNextEvent 
  496. static PatchInitCursor        pICPatch;                    // patch for InitCursor 
  497. static PatchSetCCursor        pSCCPatch;                    // patch for SetCCursor 
  498. static PatchSetCursor        pSCPatch;                    // patch for SetCursor 
  499. static PatchStillDown        pSDPatch;                    // patch for StillDown under A/UX or PowerPC
  500. static PatchWaitMouseUp        pWMUPatch;                    // patch for WaitMouseUp under A/UX 
  501.  
  502. //========================================================================================
  503. // GLOBAL Procedures
  504. //========================================================================================
  505. #undef Inherited
  506.  
  507. #if qPatchEventAvail
  508. static pascal Boolean ResetBusyEventAvail(short eventMask, EventRecord* theEvent);
  509. #endif
  510. static pascal Boolean ResetBusyGetNextEvent(short eventMask, EventRecord* theEvent);
  511. static pascal Boolean ResetBusyStillDown();
  512. static pascal Boolean ResetBusyWaitMouseUp();
  513.  
  514. #if qPowerPC
  515. static pascal void ABusyTask(VBLTaskPtr vblTaskPtr);
  516. #else
  517. static pascal void ABusyTask();
  518. #endif
  519.  
  520. //----------------------------------------------------------------------------------------
  521. // ResetBusyCursor:
  522. //----------------------------------------------------------------------------------------
  523. #pragma segment MABusyCursorRes
  524.  
  525. void TBusyCursor::ResetBusyCursor()
  526. {
  527.     if (fgBusyCursor && !fgBusyCursor->fIgnoreReset)
  528.         fgBusyCursor->Reset(fgBusyCursor->fBusyDelay);
  529. } // TBusyCursor::ResetBusyCursor
  530.  
  531. #if qPatchEventAvail
  532. pascal Boolean ResetBusyEventAvail(short eventMask, EventRecord* theEvent)
  533. {
  534.     long OldA5 = SetCurrentA5();                // ***** Called from trap patches *****
  535.     
  536.     TBusyCursor::ResetBusyCursor();
  537.     Boolean avail = pEAPatch.CallInherited(eventMask, theEvent);
  538.     
  539.     SetA5(OldA5);
  540.     
  541.     return avail;
  542. }
  543. #endif
  544.  
  545. pascal Boolean ResetBusyGetNextEvent(short eventMask, EventRecord* theEvent)
  546. {
  547.     long OldA5 = SetCurrentA5();                // ***** Called from trap patches *****
  548.     
  549.     TBusyCursor::ResetBusyCursor();
  550.     Boolean avail = pGNEPatch.CallInherited(eventMask, theEvent);
  551.     
  552.     SetA5(OldA5);
  553.     
  554.     return avail;
  555. }
  556.  
  557. pascal Boolean ResetBusyStillDown()
  558. {
  559.     long OldA5 = SetCurrentA5();                // ***** Called from trap patches *****
  560.     
  561.     TBusyCursor::ResetBusyCursor();
  562.     Boolean isStillDown = pSDPatch.CallInherited();
  563.     
  564.     SetA5(OldA5);
  565.     
  566.     return isStillDown;
  567. }
  568.  
  569. pascal Boolean ResetBusyWaitMouseUp()
  570. {
  571.     long OldA5 = SetCurrentA5();                // ***** Called from trap patches *****
  572.     
  573.     TBusyCursor::ResetBusyCursor();
  574.     Boolean isStillDown = pWMUPatch.CallInherited();
  575.     
  576.     SetA5(OldA5);
  577.     
  578.     return isStillDown;
  579. }
  580.  
  581. //----------------------------------------------------------------------------------------
  582. // SetCMacAppCursor: Must be in Main segment, and cannot call to any other segment because
  583. // SetCursor is called from the ABusyTask VBL task. The SetCCursor patch, used to remember
  584. // the color cursor being set. Installed as a "Head" patch, meaning the original
  585. // SetCCursor trap is called after this code has completed.
  586. //----------------------------------------------------------------------------------------
  587. #pragma segment MABusyCursorRes
  588.  
  589. pascal void TBusyCursor::SetCMacAppCursorPatch(CCrsrHandle theCCursor)
  590. {
  591.     long OldA5 = SetCurrentA5();                // ***** Called from trap patches *****
  592.     
  593.     if (fgBusyCursor)
  594.         fgBusyCursor->SetCMacAppCursor(theCCursor);
  595.     
  596.     pSCCPatch.CallInherited(theCCursor);
  597.     
  598.     SetA5(OldA5);
  599. } // SetCMacAppCursorPatch
  600.  
  601. #pragma segment MABusyCursorRes
  602.  
  603. pascal void TBusyCursor::SetMacAppCursorPatch(const Cursor* theCursor)
  604. {
  605.     long OldA5 = SetCurrentA5();                // ***** Called from trap patches *****
  606.  
  607.     if (fgBusyCursor)    
  608.         fgBusyCursor->SetMacAppCursor(theCursor);
  609.     
  610.     pSCPatch.CallInherited(theCursor);
  611.     
  612.     SetA5(OldA5);
  613. } // SetMacAppCursorPatch
  614.  
  615. //----------------------------------------------------------------------------------------
  616. // InitUBusyCursor:
  617. //----------------------------------------------------------------------------------------
  618. #pragma segment MAInit
  619.  
  620. void TBusyCursor::InitUBusyCursor()
  621. {
  622.     TBusyCursor* aBusyCursor = new TBusyCursor;                // Create the BusyCursor mechanism 
  623.     aBusyCursor->IBusyCursor();                    // Automatically sets fgBusyCursor 
  624.     fgBusyCursor = aBusyCursor;
  625. } // InitUBusyCursor
  626.  
  627.  
  628. //----------------------------------------------------------------------------------------
  629. // TerminateUBusyCursor:
  630. //----------------------------------------------------------------------------------------
  631. #pragma segment MABusyCursorRes
  632.  
  633. void TBusyCursor::TerminateUBusyCursor()
  634. {
  635.     gBusyCursor = (TBusyCursor *)FreeIfObject(gBusyCursor);
  636. } // TerminateUBusyCursor
  637.  
  638.  
  639. //----------------------------------------------------------------------------------------
  640. // InitMacAppCursor: Called when the InitCursor trap is executed. After completion, we
  641. // jump to the ROM InitCursor.
  642. //----------------------------------------------------------------------------------------
  643. #pragma segment MABusyCursorRes
  644.  
  645. pascal void TBusyCursor::InitMacAppCursor()
  646. {
  647.     long OldA5 = SetCurrentA5();                // ***** Called from trap patches *****
  648.     
  649.     if (fgBusyCursor)    
  650.         fgBusyCursor->SetMacAppCursor(&qd.arrow);
  651.     
  652.     pICPatch.CallInherited();
  653.     
  654.     SetA5(OldA5);
  655. } // InitMacAppCursor
  656.  
  657. //----------------------------------------------------------------------------------------
  658. // NextAnimatedCursor:
  659. //----------------------------------------------------------------------------------------
  660. #pragma segment MABusyCursorRes
  661.  
  662. CursHandle TBusyCursor::NextAnimatedCursor(AcurRsrcHandle acurRsrc)
  663. {
  664.     AcurRsrcRecord& whichAcurRsrc = **acurRsrc;    // OK: it's locked down in InitializeAnimatedCursor
  665.  
  666.     if (++whichAcurRsrc.whichCursor >= whichAcurRsrc.noOfCursors)
  667.         whichAcurRsrc.whichCursor = 0;
  668.  
  669.     return whichAcurRsrc.cursors[whichAcurRsrc.whichCursor].Memory.h;
  670. } // NextAnimatedCursor
  671.  
  672. //----------------------------------------------------------------------------------------
  673. // ABusyTask:
  674. //----------------------------------------------------------------------------------------
  675. #pragma segment MABusyCursorRes
  676.  
  677. pascal void ABusyTask(
  678. #if qPowerPC
  679.                         VBLTaskPtr vblTaskPtr
  680. #endif
  681.                                                 )
  682. {
  683.     // if we are running native PowerPC, the runtime architecture passes us a pointer to our
  684.     // VBLTask as a parameter… othewise we have to retrieve it.
  685. #if !qPowerPC
  686.     VBLTaskPtr vblTaskPtr = (VBLTaskPtr)GetParmBlockPtr();
  687. #endif
  688.         
  689.     TBusyCursor* theBusyCursor = ((QElemWithBusyCursor*)vblTaskPtr)->fBusyCursor;
  690.     if (theBusyCursor)
  691.     {
  692.         long OldA5 = SetA5(theBusyCursor->fA5);
  693.     
  694.         theBusyCursor->BusyTask();
  695.  
  696.         SetA5(OldA5);
  697.     }
  698. } // ABusyTask
  699.  
  700.  
  701. //========================================================================================
  702. // CLASS TBusyCursor
  703. //========================================================================================
  704. #undef Inherited
  705. #define Inherited TObject
  706.  
  707. #pragma segment MAInit
  708. MA_DEFINE_CLASS_M1(TBusyCursor, Inherited);
  709.  
  710. //----------------------------------------------------------------------------------------
  711. // TBusyCursor::TBusyCursor
  712. //----------------------------------------------------------------------------------------
  713. #pragma segment ConstructorRes
  714.  
  715. TBusyCursor::TBusyCursor()
  716. {
  717.     fInColor = FALSE;
  718.     fOrigCCursor = NULL;
  719.     fBusyDelay = 0;
  720.     fInControl = FALSE;
  721.     fChangeToBusy = FALSE;
  722.     fIgnoreReset = FALSE;
  723.     fBusyOn = FALSE;
  724.     fCursorState = NULL;
  725.     fAnimateDelay = 0;
  726.     fTimeoutCount = 0;
  727.     fSpinCount = 0;
  728. } // TBusyCursor::TBusyCursor
  729.  
  730. //----------------------------------------------------------------------------------------
  731. // TBusyCursor::IBusyCursor:
  732. //----------------------------------------------------------------------------------------
  733. #pragma segment MAInit
  734.  
  735. void TBusyCursor::IBusyCursor()
  736. {
  737.     this->IObject();
  738.  
  739.     FailInfo fi;
  740.     Try(fi)
  741.     {
  742.         // Setup the pCursorInfo record 
  743.         fInControl = TRUE;                // we are in control during initialization 
  744.         fOrigCursor = qd.arrow;
  745.         fBusyDelay = kBusyDelay;
  746.         fInColor = FALSE;
  747.         fChangeToBusy = TRUE;
  748.         fBusyOn = FALSE;
  749.  
  750.         fA5 = SetCurrentA5();                            // make the A5 world available to the VBL task
  751.                                                         // note: this was previously done with GetA5, but it
  752.                                                         // should be safe for us to use the PowerPC-compatible
  753.                                                         // SetCurrentA5 instead at this point…
  754.  
  755.         this->SetAnimatedCursor(kAcurRsrcID, kAnimateDelay);// init the animated cursor routine
  756.         this->SetTimeout(kTicksBeforeTimeout);            // NOTE: needs fAnimateDelay
  757.     
  758.         // Setup the VBL task 
  759.         fQElemWithBusyCursor.q.qType = vType;
  760.         FailNIL(fQElemWithBusyCursor.q.vblAddr = NewVBLProc(StripLong(ABusyTask)));
  761.         fQElemWithBusyCursor.q.vblCount = kBusyDelay;
  762.         fQElemWithBusyCursor.q.vblPhase = 0;
  763.         fQElemWithBusyCursor.fBusyCursor = this;
  764.  
  765.         // Patch the necessary traps 
  766.         pSCPatch.Install(SetMacAppCursorPatch);
  767.         pICPatch.Install(InitMacAppCursor);
  768.         if (qNeedsColorQD || HasColorQD())
  769.             pSCCPatch.Install(SetCMacAppCursorPatch);
  770.     
  771.         // Install the VBL task 
  772.         FailOSErr(VInstall((QElemPtr) & fQElemWithBusyCursor.q));
  773.         pBusyCursorVBLInstalled = TRUE;
  774.     
  775.         // Patch the traps applicable 
  776.         pGNEPatch.Install(ResetBusyGetNextEvent);
  777.         pSDPatch.Install(ResetBusyStillDown);
  778. #if qPatchEventAvail
  779.         pEAPatch.Install(ResetBusyEventAvail);
  780. #endif
  781.         if (HasAUX())
  782.             pWMUPatch.Install(ResetBusyWaitMouseUp);
  783.  
  784.         // Set busy delay 
  785.         this->SetDelay(kBusyDelay);
  786.  
  787.         fi.Success();
  788.     }
  789.     else
  790.     {
  791.         this->Free();
  792.         fi.ReSignal();
  793.     }
  794. } // TBusyCursor::IBusyCursor
  795.  
  796. //----------------------------------------------------------------------------------------
  797. // TBusyCursor::Free:
  798. //----------------------------------------------------------------------------------------
  799. #pragma segment MATerminate
  800.  
  801. TBusyCursor::~TBusyCursor()
  802. {
  803.     this->Reset(1);                                    // Restore the non-busy cursor 
  804.  
  805.     if (pBusyCursorVBLInstalled)
  806.         VRemove((QElemPtr) & fQElemWithBusyCursor.q);    // Remove the VBL task 
  807.  
  808.     this->ReleaseAnimatedCursor();
  809.  
  810.     // Unpatch the patches 
  811.     pICPatch.UnpatchTrap();
  812.     pSCPatch.UnpatchTrap();
  813.     if (qNeedsColorQD || HasColorQD())
  814.         pSCCPatch.UnpatchTrap();
  815.  
  816.     pGNEPatch.UnpatchTrap();
  817.     pSDPatch.UnpatchTrap();
  818. #if qPatchEventAvail
  819.     pEAPatch.UnpatchTrap();
  820. #endif
  821.     if (HasAUX())
  822.         pWMUPatch.UnpatchTrap();
  823. } // TBusyCursor::Free
  824.  
  825. //----------------------------------------------------------------------------------------
  826. // TBusyCursor::Reset:
  827. //----------------------------------------------------------------------------------------
  828. #pragma segment MABusyCursorRes
  829.  
  830. void TBusyCursor::Reset(short delayTicks)
  831. {
  832.     if (fInControl && fChangeToBusy)
  833.     {
  834.         if (fBusyOn)
  835.             if (fInColor)
  836.                 SetCCursor(fOrigCCursor);
  837.             else
  838.                 SetCursor(&(fOrigCursor));
  839.         fQElemWithBusyCursor.q.vblCount = delayTicks;
  840.     }
  841. } // TBusyCursor::Reset
  842.  
  843. //----------------------------------------------------------------------------------------
  844. // TBusyCursor::Activate:
  845. //----------------------------------------------------------------------------------------
  846. #pragma segment MABusyCursorRes
  847.  
  848. Boolean TBusyCursor::Activate(Boolean entering)
  849. {
  850.     return this->InControl(entering, TRUE);
  851. } // TBusyCursor::Activate
  852.  
  853. //----------------------------------------------------------------------------------------
  854. // TBusyCursor::InControl:
  855. //----------------------------------------------------------------------------------------
  856. #pragma segment MABusyCursorRes
  857.  
  858. Boolean TBusyCursor::InControl(Boolean entering, Boolean reset)
  859. {
  860.     if (reset)
  861.         this->Reset(fBusyDelay);
  862.  
  863.     Boolean returnVal = fInControl;
  864.     fInControl = entering;
  865.  
  866.     return returnVal;
  867. } // TBusyCursor::InControl
  868.  
  869. //----------------------------------------------------------------------------------------
  870. // TBusyCursor::SetDelay:
  871. //----------------------------------------------------------------------------------------
  872. #pragma segment MABusyCursorRes
  873.  
  874. void TBusyCursor::SetDelay(short newDelay)
  875. {
  876.     if (newDelay > 0)                            // save new delay time 
  877.     {
  878.         fBusyDelay = newDelay;
  879.         this->Reset(newDelay);                        // reset timer 
  880.     }
  881. } // TBusyCursor::SetDelay
  882.  
  883. //----------------------------------------------------------------------------------------
  884. // TBusyCursor::ForceBusy: Trigger on next tick and reset timer
  885. //----------------------------------------------------------------------------------------
  886. #pragma segment MABusyCursorRes
  887.  
  888. void TBusyCursor::ForceBusy()
  889. {
  890.     this->Reset(1);
  891. } // TBusyCursor::ForceBusy
  892.  
  893. //----------------------------------------------------------------------------------------
  894. // TBusyCursor::TurnOff: This is called from InitMacAppCursor, SetMacAppCursor and
  895. // SetCMacAppCursor. It sets pCursorInfo fields to indicate that the cursor is not the
  896. // busy cursor.
  897. //----------------------------------------------------------------------------------------
  898. #pragma segment MABusyCursorRes
  899.  
  900. void TBusyCursor::TurnOff()
  901. {
  902.     if (fInControl && fChangeToBusy)
  903.     {
  904.         fBusyOn = FALSE;                // anyone that sets the busy cursor should set this true explicitly
  905.         fQElemWithBusyCursor.q.vblCount = fBusyDelay;
  906.     }
  907. } // TBusyCursor::TurnOff
  908.  
  909. //----------------------------------------------------------------------------------------
  910. // TBusyCursor::InitializeAnimatedCursor:
  911. //----------------------------------------------------------------------------------------
  912. #pragma segment MAInit
  913.  
  914. AcurRsrcHandle TBusyCursor::InitializeAnimatedCursor(ResNumber acurRsrcId)
  915. {
  916.     ReserveMem(sizeof(AcurRsrcRecord)); // so it will load low
  917.     AcurRsrcHandle acurRsrc = (AcurRsrcHandle)GetResource('acur', acurRsrcId);
  918.  
  919.     if (acurRsrc)
  920.     {
  921.         DetachResource((Handle)acurRsrc); // cause we do bookkeeping in it. Don't want to dirty orig.
  922.         HNoPurge((Handle)acurRsrc);
  923.         HLock((Handle)acurRsrc);
  924.         (*acurRsrc)->whichCursor = 0;
  925.  
  926.         // Load each cursor in the sequence and lock them in memory 
  927.         for (short i = 0; i < (*acurRsrc)->noOfCursors; ++i)
  928.         {
  929.             ReserveMem(sizeof(Cursor)); // so it will load low
  930.             CursHandle theCursor = GetCursor((*acurRsrc)->cursors[i].Disk.rsrcId);// Get the cursor from the disk
  931.             FailNILResource((Handle)theCursor);
  932.             (*acurRsrc)->cursors[i].Memory.h = theCursor;    // remember the cursor
  933.             HNoPurge((Handle)theCursor);
  934.             HLock((Handle)theCursor);            // Make sure it is locked
  935.         }
  936.     }
  937.  
  938.     return acurRsrc;
  939. } // TBusyCursor::InitializeAnimatedCursor
  940.  
  941. //----------------------------------------------------------------------------------------
  942. // TBusyCursor::Animate:
  943. //----------------------------------------------------------------------------------------
  944. #pragma segment MABusyCursorRes
  945.  
  946. void TBusyCursor::Animate()
  947. {
  948.     fSpinCount = 0;                    // zero spins since we last heard from the app
  949. } // TBusyCursor::Animate
  950.  
  951. //----------------------------------------------------------------------------------------
  952. // TBusyCursor::SetTimeout:
  953. //----------------------------------------------------------------------------------------
  954. #pragma segment MABusyCursorRes
  955.  
  956. void TBusyCursor::SetTimeout(long ticksBeforeTimeout)
  957. {
  958.     fTimeoutCount = ticksBeforeTimeout / fAnimateDelay;
  959.     fSpinCount = 0;
  960. } // TBusyCursor::SetTimeout
  961.  
  962. //----------------------------------------------------------------------------------------
  963. // TBusyCursor::KeepCursorBusy:
  964. //----------------------------------------------------------------------------------------
  965. #pragma segment MABusyCursorRes
  966.  
  967. Boolean TBusyCursor::KeepCursorBusy(Boolean keepItSpinning)
  968. {
  969.     Boolean currentSetting = fIgnoreReset;
  970.     fIgnoreReset = keepItSpinning;
  971.     return currentSetting;
  972. }
  973.  
  974. //----------------------------------------------------------------------------------------
  975. // TBusyCursor::SetAnimatedCursor:
  976. //----------------------------------------------------------------------------------------
  977. #pragma segment MABusyCursorRes
  978.  
  979. void TBusyCursor::SetAnimatedCursor(ResNumber itsACUR, short animateDelay)
  980. {
  981.     Boolean wasInControl = fInControl;
  982.     fInControl = FALSE; // so the vbl doesn't whack us!
  983.  
  984.     this->ReleaseAnimatedCursor();
  985.  
  986.     fCursorState = this->InitializeAnimatedCursor(itsACUR);// init the animated cursor routine
  987.     if (fCursorState)
  988.         fCurrentCursor = **NextAnimatedCursor(fCursorState);// get the first cursor
  989.     else
  990.         fCurrentCursor = **GetCursor(watchCursor);
  991.  
  992.     fAnimateDelay = animateDelay;
  993.  
  994.     fInControl = wasInControl;
  995. }
  996.  
  997.  
  998. //----------------------------------------------------------------------------------------
  999. // TBusyCursor::ReleaseAnimatedCursor:
  1000. //----------------------------------------------------------------------------------------
  1001. #pragma segment MABusyCursorRes
  1002.  
  1003. void TBusyCursor::ReleaseAnimatedCursor()
  1004. {
  1005.     if (fCursorState)
  1006.     {
  1007.         for (short i = 0; i < (*fCursorState)->noOfCursors; ++i)
  1008.             ReleaseResource((Handle)(*fCursorState)->cursors[i].Memory.h);
  1009.         fCursorState = (AcurRsrcHandle)DisposeIfHandle((Handle)fCursorState);
  1010.     }
  1011. }
  1012.  
  1013. //----------------------------------------------------------------------------------------
  1014. // SetMacAppCursor: Must be in Main segment, and cannot call to any other segment because
  1015. // SetCursor is called from the ABusyTask VBL task. Patches SetCursor to remember the
  1016. // cursor being set. Installed as a "Head" patch, meaning the original SetCursor trap is
  1017. // called after this code has completed. Also called from InitMacAppCursor.
  1018. //----------------------------------------------------------------------------------------
  1019. #pragma segment MABusyCursorRes
  1020.  
  1021. void TBusyCursor::SetMacAppCursor(const Cursor* theCursor)
  1022. {
  1023.     this->TurnOff();
  1024.  
  1025.     // If we are setting the cursor to the busy cursor, then don't save it 
  1026.     if (theCursor != &fCurrentCursor)
  1027.     {
  1028.         fInColor = FALSE;
  1029.         fOrigCursor = *theCursor;
  1030.     }
  1031.     else
  1032.         fBusyOn = TRUE;                // because BusyTurnOff set it to false
  1033. } // SetMacAppCursor
  1034.  
  1035. //----------------------------------------------------------------------------------------
  1036. // SetCMacAppCursor: Must be in Main segment, and cannot call to any other segment because
  1037. // SetCursor is called from the ABusyTask VBL task. The SetCCursor patch, used to remember
  1038. // the color cursor being set. Installed as a "Head" patch, meaning the original
  1039. // SetCCursor trap is called after this code has completed.
  1040. //----------------------------------------------------------------------------------------
  1041. #pragma segment MABusyCursorRes
  1042.  
  1043. void TBusyCursor::SetCMacAppCursor(CCrsrHandle theCCursor)
  1044. {
  1045.     this->TurnOff();
  1046.  
  1047.     fInColor = TRUE;
  1048.     fOrigCCursor = theCCursor;        // Save a copy of the color cursor 
  1049. } // SetCMacAppCursor
  1050.  
  1051. //----------------------------------------------------------------------------------------
  1052. // TBusyCursor::BusyTask
  1053. //----------------------------------------------------------------------------------------
  1054. #pragma segment MABusyCursorRes
  1055.  
  1056. void TBusyCursor::BusyTask()
  1057. {
  1058.     // always Reset the vblCount 
  1059.     fQElemWithBusyCursor.q.vblCount = fBusyDelay;
  1060.  
  1061.     if (!LMGetCrsrBusy() && fInControl && fChangeToBusy)
  1062.         if (fCursorState)            // if we have an animated cursor 
  1063.         {
  1064.             if (!fBusyOn)
  1065.                 fSpinCount = 0;
  1066.             if (fSpinCount <= fTimeoutCount)
  1067.             {
  1068.                 fCurrentCursor = **NextAnimatedCursor(fCursorState);
  1069.                 SetCursor(&fCurrentCursor);
  1070.                 ++fSpinCount;
  1071.             }
  1072.             fQElemWithBusyCursor.q.vblCount = fAnimateDelay;
  1073.         }
  1074.         else if (!fBusyOn)
  1075.             SetCursor(&fCurrentCursor);
  1076.  
  1077. } // BusyTask
  1078.  
  1079.  
  1080. //----------------------------------------------------------------------------------------
  1081. // End of UBusyCursor.cp
  1082.  
  1083. #pragma segment Inline
  1084.